local Stack = {}
Stack.__cname = "util.Stack"
Stack.__index = Stack

local ClearTypeEnum = {
    Reset = nil,
    FillNil = 1,
    Keep = 2,
}
Stack.ClearTypeEnum = ClearTypeEnum

function Stack.new2(src)
    assert("util.Stack" == src.__cname, "InvalidArgument: not Stack")
    local s = Stack.new()
    s.count = src.count
    for i=1,src.count do
        s.arr[i] = src.arr[i]
    end
    return s
end

function Stack.new()
    local obj = {}
    setmetatable(obj, Stack)
    obj:ctor()
    return obj
end

function Stack:ctor()
    self.arr = {}
    self.count = 0
end

function Stack:Clear(clearType)
    if clearType == ClearTypeEnum.Reset then
        self.arr = {}
    elseif clearType == ClearTypeEnum.FillNil then
        for i=1,self.count do
            self.arr[i] = nil
        end
    end
    self.count = 0
end

function Stack:GetCount()
    return self.count
end

function Stack:Push(v)
    self.count = self.count + 1
    self.arr[self.count] = v
end

function Stack:Pop()
    assert(self.count > 0, "out of range")
    local v = self.arr[self.count]
    self.arr[self.count] = nil
    self.count = self.count - 1
    return v
end

function Stack:Peek()
    if self.count > 0 then
        return self.arr[self.count]
    end
    return nil
end

function Stack:Contains(v)
    for i=1,self.count do
        if self.arr[i] == v then
            return true
        end
    end
    return false
end

function Stack:GetIterator()
    local iteratorCur = self.count
    local function iterator(tb, key)
        if iteratorCur < 1 then
            return nil
        end
        local ret = self.arr[iteratorCur]
        iteratorCur = iteratorCur - 1
        return ret
    end
    return iterator
end

function Stack:__tostring()
    if self.count < 1 then return "" end
    local strTb = {}
    for i=1,self.count do
        local item = self.arr[i]
        table.insert(strTb, tostring(item))
    end
    return table.concat(strTb, ",")
end

return Stack
